<template>
  <div class="card chat">
    <t-chat layout="both" :clear-history="chatList.length > 0 && !isStreamLoad" @on-action="operation" @clear="clearConfirm">
      <template v-for="(item, index) in chatList" :key="index">
        <t-chat-item
          :role="item.role"
          :content="item.content"
          :text-loading="index === 0 && loading"
          :variant="getStyle(item.role)"
          :avatar="item.avatar"
          :reasoning="{
            collapsed: index === 0 && !isStreamLoad,
            expandIconPlacement: 'right',
            onExpandChange: handleChange,
            collapsePanelProps: {
              header: renderHeader(index === 0 && isStreamLoad && !item.content, item),
              content: renderReasoningContent(item.reasoning || '')
            }
          }"
        >
          <template v-if="!isStreamLoad" #actions>
            <t-chat-action
              :is-good="isGood"
              :item-index="index"
              :is-bad="isBad"
              :content="item.content"
              @operation="handleOperation"
            />
          </template>
        </t-chat-item>
      </template>
      <template #footer>
        <t-chat-sender
          v-model="inputValue"
          :loading="isStreamLoad"
          :textarea-props="{
            placeholder: '请输入消息...'
          }"
          @stop="onStop"
          @send="inputEnter"
        >
          <template #prefix>
            <div class="model-select">
              <t-tooltip v-model:visible="allowToolTip" content="切换模型" trigger="hover">
                <t-select
                  v-model="selectValue"
                  :options="selectOptions"
                  value-type="object"
                  @focus="allowToolTip = false"
                ></t-select>
              </t-tooltip>
              <t-button class="check-box" :class="{ 'is-active': isChecked }" variant="text" @click="checkClick">
                <SystemSumIcon />
                <span>深度思考</span>
              </t-button>
            </div>
          </template>
        </t-chat-sender>
      </template>
    </t-chat>
  </div>
</template>
<script setup lang="tsx">
import { ref } from "vue";
import { CheckCircleIcon } from "tdesign-icons-vue-next";
import { SystemSumIcon } from "tdesign-icons-vue-next";
// 定义聊天消息类型
interface ChatMessage {
  avatar?: string;
  content: string;
  role: "user" | "assistant" | "error";
  reasoning?: string;
  duration?: number;
}
const loading = ref(false);
const isStreamLoad = ref(false);
const isGood = ref(false);
const isBad = ref(false);
const inputValue = ref("");
const allowToolTip = ref(false);
const isChecked = ref(false);
const selectOptions = [
  {
    label: "默认模型",
    value: "default"
  },
  {
    label: "deepseek-r1",
    value: "deepseek-r1"
  },
  {
    label: "混元",
    value: "hunyuan"
  }
];
const selectValue = ref({
  label: "默认模型",
  value: "default"
});
const renderHeader = (flag: boolean, item: ChatMessage) => {
  if (flag) {
    return <t-chat-loading text="思考中..." />;
  }
  const endText = item.duration ? `已深度思考(用时${item.duration}秒)` : "已深度思考";
  return (
    <div style="display:flex;align-items:center">
      <CheckCircleIcon
        style={{
          color: "var(--td-success-color-5)",
          fontSize: "20px",
          marginRight: "8px"
        }}
      />
      <span>{endText}</span>
    </div>
  );
};
const renderReasoningContent = (reasoningContent: string) => <t-chat-content content={reasoningContent} role="assistant" />;
const checkClick = () => {
  isChecked.value = !isChecked.value;
};
const getStyle = (role: string) => {
  if (role === "assistant") {
    return "outline";
  }
  if (role === "user") {
    return "base";
  }
  if (role === "error") {
    return "text";
  }
  return "text";
};

const handleOperation = function (type: string, options: { index: number }) {
  const { index } = options;
  if (type === "good") {
    isGood.value = !isGood.value;
    isBad.value = false;
  } else if (type === "bad") {
    isBad.value = !isBad.value;
    isGood.value = false;
  } else if (type === "replay") {
    const userQuery = chatList.value[index + 1].content;
    inputEnter(userQuery);
  }
};
// 倒序渲染
const chatList = ref<ChatMessage[]>([]);
const operation = function (type: string, options: any) {
  console.log(type, options);
};
const clearConfirm = function () {
  chatList.value = [];
};
const onStop = function () {
  isStreamLoad.value = false;
  loading.value = false;
  // 如果有正在进行的请求，可以在这里中断
};
const inputEnter = function (inputValue: string) {
  if (isStreamLoad.value) {
    return;
  }
  if (!inputValue) return;
  const params: ChatMessage = {
    avatar: "https://tdesign.gtimg.com/site/avatar.jpg",
    content: inputValue,
    role: "user" as const
  };
  chatList.value.unshift(params);
  // 空消息占位
  const params2: ChatMessage = {
    avatar: "https://tdesign.gtimg.com/site/chat-avatar.png",
    content: "",
    role: "assistant" as const
  };
  chatList.value.unshift(params2);
  handleData(inputValue);
};
const sendMessage = async (message: string) => {
  try {
    const lastItem = chatList.value[0];

    const response = await fetch("https://api.siliconflow.cn/v1/chat/completions", {
      method: "POST",
      headers: {
        Authorization: "Bearer sk-wwuovgjwcpbmjplzcnnwqelqmdjdyfafbjgecequosmnkgfx",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        model: "Qwen/Qwen2.5-7B-Instruct",
        messages: [{ role: "user", content: message }],
        stream: true,
        max_tokens: 512,
        temperature: 0.7,
        top_p: 0.7
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const reader = response.body?.getReader();
    const decoder = new TextDecoder();

    if (!reader) {
      throw new Error("无法获取流读取器");
    }

    try {
      while (true) {
        const { done, value } = await reader.read();

        if (done) {
          isStreamLoad.value = false;
          loading.value = false;
          break;
        }

        const chunk = decoder.decode(value, { stream: true });
        const lines = chunk.split("\n");

        for (const line of lines) {
          if (line.startsWith("data: ")) {
            const data = line.slice(6);

            if (data === "[DONE]") {
              isStreamLoad.value = false;
              loading.value = false;
              return;
            }

            try {
              const parsed = JSON.parse(data);
              const content = parsed.choices?.[0]?.delta?.content;

              if (content) {
                loading.value = false;
                lastItem.content += content;
              }
            } catch (parseError) {
              console.warn("解析JSON失败:", parseError);
            }
          }
        }
      }
    } finally {
      reader.releaseLock();
    }
  } catch (error: any) {
    console.error("API调用失败:", error);
    isStreamLoad.value = false;
    loading.value = false;

    // 错误处理
    const lastItem = chatList.value[0];
    lastItem.role = "error";
    lastItem.content = `请求失败: ${error.message}`;

    throw error;
  }
};
const handleData = async (value: string) => {
  loading.value = true;
  isStreamLoad.value = true;
  await sendMessage(value);
};
const handleChange = (value: any, { index }: { index: number }) => {
  console.log("handleChange", value, index);
};
</script>
<style lang="scss" scoped>
.chat {
  height: 100%;
}
::-webkit-scrollbar-thumb {
  background-color: var(--td-scrollbar-color);
}
::-webkit-scrollbar-thumb:horizontal:hover {
  background-color: var(--td-scrollbar-hover-color);
}
::-webkit-scrollbar-track {
  background-color: var(--td-scroll-track-color);
}
.chat-box {
  position: relative;
  .bottomBtn {
    position: absolute;
    bottom: 210px;
    left: 50%;
    width: 40px;
    height: 40px;
    padding: 0;
    margin-left: -20px;
    border: 0;
    border-radius: 50%;
    box-shadow: 0 8px 10px -5px rgb(0 0 0 / 8%), 0 16px 24px 2px rgb(0 0 0 / 4%), 0 6px 30px 5px rgb(0 0 0 / 5%);
  }
  .to-bottom {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    font-size: 24px;
    line-height: 40px;
    background: var(--td-bg-color-container);
    border: 1px solid #dcdcdc;
    border-radius: 50%;
    .t-icon {
      font-size: 24px;
    }
  }
}
:deep(.model-select) {
  display: flex;
  align-items: center;
  .t-select {
    width: 112px;
    height: var(--td-comp-size-m);
    margin-right: var(--td-comp-margin-s);
    .t-input {
      padding: 0 15px;
      border-radius: 32px;
    }
    .t-input.t-is-focused {
      box-shadow: none;
    }
  }
  .check-box {
    box-sizing: border-box;
    flex: 0 0 auto;
    width: 112px;
    height: var(--td-comp-size-m);
    color: var(--td-text-color-primary);
    background: var(--td-bg-color-component);
    border: 0;
    border-radius: 32px;
    .t-button__text {
      display: flex;
      align-items: center;
      justify-content: center;
      span {
        margin-left: var(--td-comp-margin-xs);
      }
    }
  }
  .check-box.is-active {
    color: var(--td-text-color-brand);
    background: var(--td-brand-color-light);
    border: 1px solid var(--td-brand-color-focus);
  }
}
</style>
